/**
 * @author nttdocomo
 */
define(function(require) {
	require('./abstractView');
	aries.klass("aries.view.View", aries.view.AbstractView.extend({

		// private
		afterRender : function() {
			var me = this;
			aries.view.AbstractView.prototype.afterRender.apply(this, arguments);
			me.getTargetEl().on({
				'mouseenter' : _.bind(me.handleEvent, me),
				'mouseleave' : _.bind(me.handleEvent, me),
				'click' : _.bind(me.handleEvent, me)
			}, 'li')
			/*me.mon(me.getTargetEl(), {
			 scope : me,
			 freezeEvent : true,
			 click : me.handleEvent,
			 mousedown : me.handleEvent,
			 mouseup : me.handleEvent,
			 dblclick : me.handleEvent,
			 contextmenu : me.handleEvent,
			 mouseover : me.handleEvent,
			 mouseout : me.handleEvent,
			 keydown : me.handleEvent
			 });*/
		},

		/**
		 * Highlights a given item in the DataView. This is called by the mouseover handler if {@link #overItemCls}
		 * and {@link #trackOver} are configured, but can also be called manually by other code, for instance to
		 * handle stepping through the list via keyboard navigation.
		 * @param {HTMLElement} item The item to highlight
		 */
		highlightItem : function(item) {
			var me = this;
			me.clearHighlight();
			me.highlightedItem = item;
			item.addClass(me.overItemCls);
			me.trigger('highlightitem', me, item);
		},

		/**
		 * Un-highlights the currently highlighted item, if any.
		 */
		clearHighlight : function() {
			var me = this, highlighted = me.highlightedItem;

			if (highlighted) {
				highlighted.removeClass(me.overItemCls);
				me.trigger('unhighlightitem', me, highlighted);
				delete me.highlightedItem;
			}
		},

		handleEvent : function(e) {
			var key = e.type == 'keydown' && e.getKey();

			if (this.processUIEvent(e) !== false) {
				this.processSpecialEvent(e);
			}

			// After all listeners have processed the event, prevent browser's default action
			// on SPACE which is to focus the event's target element.
			// Focusing causes the browser to attempt to scroll the element into view.
			if (key === e.SPACE) {
				e.stopEvent();
			}
		},

		// private
		onItemMouseEnter : function(record, item, index, e) {
			if (this.trackOver) {
				this.highlightItem(item);
			}
		},

		// private
		onItemMouseLeave : function(record, item, index, e) {
			if (this.trackOver) {
				this.clearHighlight();
			}
		},

		// @private, template methods
		onItemMouseDown : aries.emptyFn,
		onItemMouseUp : aries.emptyFn,
		onItemFocus : aries.emptyFn,
		onItemClick : aries.emptyFn,
		onItemDblClick : aries.emptyFn,
		onItemContextMenu : aries.emptyFn,
		onItemKeyDown : aries.emptyFn,
		onBeforeItemMouseDown : aries.emptyFn,
		onBeforeItemMouseUp : aries.emptyFn,
		onBeforeItemFocus : aries.emptyFn,
		onBeforeItemMouseEnter : aries.emptyFn,
		onBeforeItemMouseLeave : aries.emptyFn,
		onBeforeItemClick : aries.emptyFn,
		onBeforeItemDblClick : aries.emptyFn,
		onBeforeItemContextMenu : aries.emptyFn,
		onBeforeItemKeyDown : aries.emptyFn,

		// @private, template methods
		onContainerMouseDown : aries.emptyFn,
		onContainerMouseUp : aries.emptyFn,
		onContainerMouseOver : aries.emptyFn,
		onContainerMouseOut : aries.emptyFn,
		onContainerClick : aries.emptyFn,
		onContainerDblClick : aries.emptyFn,
		onContainerContextMenu : aries.emptyFn,
		onContainerKeyDown : aries.emptyFn,
		onBeforeContainerMouseDown : aries.emptyFn,
		onBeforeContainerMouseUp : aries.emptyFn,
		onBeforeContainerMouseOver : aries.emptyFn,
		onBeforeContainerMouseOut : aries.emptyFn,
		onBeforeContainerClick : aries.emptyFn,
		onBeforeContainerDblClick : aries.emptyFn,
		onBeforeContainerContextMenu : aries.emptyFn,
		onBeforeContainerKeyDown : aries.emptyFn,
		processItemEvent : aries.emptyFn,

		// Private template method
		processItemEvent : aries.emptyFn,
		processContainerEvent : aries.emptyFn,
		processSpecialEvent : aries.emptyFn,

		processUIEvent : function(e) {
			var me = this, item = $(e.target).closest(me.getItemSelector()), map = this.constructor.EventMap, index, record, type = e.type, overItem = me.mouseOverItem, newType;

			if (!item) {
				if (type == 'mouseover' && me.stillOverItem(e, overItem)) {
					item = overItem;
				}

				// Try to get the selected item to handle the keydown event, otherwise we'll just fire a container keydown event
				if (type == 'keydown') {
					record = me.getSelectionModel().getLastSelected();
					if (record) {
						item = me.getNode(record);
					}
				}
			}

			if (item) {
				index = me.indexOf(item);
				if (!record) {
					record = me.getRecord(item);
				}

				// It is possible for an event to arrive for which there is no record... this
				// can happen with dblclick where the clicks are on removal actions (think a
				// grid w/"delete row" action column)
				if (!record || me.processItemEvent(record, item, index, e) === false) {
					return false;
				}

				/*newType = me.isNewItemEvent(item, e);*/
				newType = type;
				if (newType === false) {
					return false;
				}

				if ((me['onBeforeItem' + map[newType]](record, item, index, e) === false) || (me.trigger('beforeitem' + newType, me, record, item, index, e) === false) || (me['onItem' + map[newType]](record, item, index, e) === false)) {
					return false;
				}

				me.trigger('item' + newType, me, record, item, index, e);
			} else {
				if ((me.processContainerEvent(e) === false) || (me['onBeforeContainer' + map[type]](e) === false) || (me.fireEvent('beforecontainer' + type, me, e) === false) || (me['onContainer' + map[type]](e) === false)) {
					return false;
				}

				me.fireEvent('container' + type, me, e);
			}

			return true;
		},

		refresh : function() {
			this.clearHighlight();
			aries.view.AbstractView.prototype.refresh.apply(this, arguments);
		}
	}, {
		EventMap : {
			mousedown : 'MouseDown',
			mouseup : 'MouseUp',
			click : 'Click',
			dblclick : 'DblClick',
			contextmenu : 'ContextMenu',
			mouseover : 'MouseOver',
			mouseout : 'MouseOut',
			mouseenter : 'MouseEnter',
			mouseleave : 'MouseLeave',
			keydown : 'KeyDown',
			focus : 'Focus'
		}
	}))
})
